﻿using System;
using System.Text;

namespace Fwql.Net.Extensions
{
    public static class MathExtension
    {
        #region Clamp

        /// <summary>
        /// 限定值在指定范围内
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="max">上限</param>
        /// <param name="min">下限</param>
        /// <returns></returns>
        public static int Clamp(this int value, int min, int max)
        {
            value = value > max ? max : value;
            return value < min ? min : value;
        }

        /// <summary>
        /// 限定值在指定范围内
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="max">上限</param>
        /// <param name="min">下限</param>
        /// <returns></returns>
        public static double Clamp(this double value, double min, double max)
        {
            value = value > max ? max : value;
            return value < min ? min : value;
        }

        /// <summary>
        /// 限定值在指定范围内
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="max">上限</param>
        /// <param name="min">下限</param>
        /// <returns></returns>
        public static float Clamp(this float value, float min, float max)
        {
            value = value > max ? max : value;
            return value < min ? min : value;
        }

        #endregion

        #region Max

        /// <summary>
        /// 取出两数中较大的一个
        /// </summary>
        /// <param name="inputA">值1</param>
        /// <param name="inputB">值2</param>
        /// <returns></returns>
        public static int MaxWith(this int inputA, int inputB)
        {
            return inputA > inputB ? inputA : inputB;
        }

        /// <summary>
        /// 取出两数中较大的一个
        /// </summary>
        /// <param name="inputA">值1</param>
        /// <param name="inputB">值2</param>
        /// <returns></returns>
        public static double MaxWith(this double inputA, double inputB)
        {
            return inputA > inputB ? inputA : inputB;
        }

        /// <summary>
        /// 取出两数中较大的一个
        /// </summary>
        /// <param name="inputA">值1</param>
        /// <param name="inputB">值2</param>
        /// <returns></returns>
        public static float MaxWith(this float inputA, float inputB)
        {
            return inputA > inputB ? inputA : inputB;
        }

        #endregion

        #region Min

        /// <summary>
        /// 取出两数中较小的一个
        /// </summary>
        /// <param name="inputA">值1</param>
        /// <param name="inputB">值2</param>
        /// <returns></returns>
        public static int MinWith(this int inputA, int inputB)
        {
            return inputA < inputB ? inputA : inputB;
        }

        /// <summary>
        /// 取出两数中较小的一个
        /// </summary>
        /// <param name="inputA">值1</param>
        /// <param name="inputB">值2</param>
        /// <returns></returns>
        public static double MinWith(this double inputA, double inputB)
        {
            return inputA < inputB ? inputA : inputB;
        }

        /// <summary>
        /// 取出两数中较小的一个
        /// </summary>
        /// <param name="inputA">值1</param>
        /// <param name="inputB">值2</param>
        /// <returns></returns>
        public static float MinWith(this float inputA, float inputB)
        {
            return inputA < inputB ? inputA : inputB;
        }

        #endregion

        #region Other

        /// <summary>
        /// 格式化数字字符串
        /// </summary>
        /// <param name="number">数字字符串</param>
        /// <param name="spacing">间距</param>
        /// <param name="separator">分隔符</param>
        /// <returns>格式化后的字符串<example>FormatNumeric("1234567890",4,',')</example></returns>
        public static string FormatNumeric(double number, int spacing = 4, char separator = ',')
        {
            string postfix = string.Empty;
            string integer = number.ToString();
            if (integer.IndexOf('.') > 0)
            {
                postfix = integer.Substring(integer.IndexOf('.') + 1);
                integer = integer.Remove(integer.IndexOf('.'));
            }

            var tmp = new StringBuilder();
            int len = 0;
            for (int i = integer.Length - 1; i >= 0; i--)
            {
                len++;
                tmp.Append(integer[i]);
                if (len != spacing)
                    continue;
                if (i == 0)
                    break;
                tmp.Append(separator);
                len = 0;
            }

            return tmp.ToString().Reverse().Append(".", postfix);
        }

        /// <summary>
        /// 格式化数字字符串
        /// </summary>
        /// <param name="number">数字字符串</param>
        /// <param name="spacing">间距</param>
        /// <param name="separator">分隔符</param>
        /// <returns>格式化后的字符串<example>FormatNumeric("1234567890",4,',')</example></returns>
        public static string FormatNumeric(decimal number, int spacing = 4, char separator = ',')
        {
            string postfix = string.Empty;
            string integer = number.ToString();
            if (integer.IndexOf('.') > 0)
            {
                postfix = integer.Substring(integer.IndexOf('.') + 1);
                integer = integer.Remove(integer.IndexOf('.'));
            }

            var tmp = new StringBuilder();
            int len = 0;
            for (int i = integer.Length - 1; i >= 0; i--)
            {
                len++;
                tmp.Append(integer[i]);
                if (len != spacing)
                    continue;
                if (i == 0)
                    break;
                tmp.Append(separator);
                len = 0;
            }

            return tmp.ToString().Reverse().Append(".", postfix);
        }

        /// <summary> 
        /// 转换人民币大写金额 
        /// </summary> 
        /// <param name="num">金额</param> 
        /// <returns>返回大写形式</returns> 
        public static string ToChineseCurrency(double num)
        {
            const string str1 = "零壹贰叁肆伍陆柒捌玖";
            string str2 = "萬仟佰拾亿仟佰拾萬仟佰拾元角分"; //数字位所对应的汉字 
            string str5 = string.Empty; //人民币大写金额形式 
            int i; //循环变量 
            string ch2 = string.Empty; //数字位的汉字读法 
            int nzero = 0; //用来计算连续的零值是几个 

            num = Math.Round(Math.Abs(num), 2); //将num取绝对值并四舍五入取2位小数 
            string str4 = ((long)(num * 100)).ToString();
            int j = str4.Length;
            if (j > 15)
            {
                return "溢出";
            }
            str2 = str2.Substring(15 - j); //取出对应位数的str2的值。如：200.55,j为5所以str2=佰拾元角分 

            //循环取出每一位需要转换的值 
            for (i = 0; i < j; i++)
            {
                string str3 = str4.Substring(i, 1); //从原num值中取出的值 
                int temp = Convert.ToInt32(str3); //从原num值中取出的值 
                string ch1; //数字的汉语读法 
                if (i != (j - 3) && i != (j - 7) && i != (j - 11) && i != (j - 15))
                {
                    //当所取位数不为元、万、亿、万亿上的数字时 
                    if (str3 == "0")
                    {
                        ch1 = string.Empty;
                        ch2 = string.Empty;
                        nzero = nzero + 1;
                    }
                    else
                    {
                        if (str3 != "0" && nzero != 0)
                        {
                            ch1 = "零" + str1.Substring(temp * 1, 1);
                            ch2 = str2.Substring(i, 1);
                            nzero = 0;
                        }
                        else
                        {
                            ch1 = str1.Substring(temp * 1, 1);
                            ch2 = str2.Substring(i, 1);
                            nzero = 0;
                        }
                    }
                }
                else
                {
                    //该位是万亿，亿，万，元位等关键位 
                    if (str3 != "0" && nzero != 0)
                    {
                        ch1 = "零" + str1.Substring(temp * 1, 1);
                        ch2 = str2.Substring(i, 1);
                        nzero = 0;
                    }
                    else
                    {
                        if (str3 != "0" && nzero == 0)
                        {
                            ch1 = str1.Substring(temp * 1, 1);
                            ch2 = str2.Substring(i, 1);
                            nzero = 0;
                        }
                        else
                        {
                            if (str3 == "0" && nzero >= 3)
                            {
                                ch1 = string.Empty;
                                ch2 = string.Empty;
                                nzero = nzero + 1;
                            }
                            else
                            {
                                if (j >= 11)
                                {
                                    ch1 = string.Empty;
                                    nzero = nzero + 1;
                                }
                                else
                                {
                                    ch1 = string.Empty;
                                    ch2 = str2.Substring(i, 1);
                                    nzero = nzero + 1;
                                }
                            }
                        }
                    }
                }
                if (i == (j - 11) || i == (j - 3))
                {
                    //如果该位是亿位或元位，则必须写上 
                    ch2 = str2.Substring(i, 1);
                }
                str5 = str5 + ch1 + ch2;

                if (i == j - 1 && str3 == "0")
                {
                    //最后一位（分）为0时，加上“整” 
                    str5 = str5 + "整";
                }
            }
            if (num == 0)
            {
                str5 = "零元整";
            }
            return str5;
        }

        /// <summary> 
        /// 转换人民币大写金额 
        /// </summary> 
        /// <param name="num">金额</param> 
        /// <returns>返回大写形式</returns> 
        public static string ToChineseCurrency(decimal num)
        {
            const string str1 = "零壹贰叁肆伍陆柒捌玖";
            string str2 = "萬仟佰拾亿仟佰拾萬仟佰拾元角分"; //数字位所对应的汉字 
            string str5 = string.Empty; //人民币大写金额形式 
            int i; //循环变量 
            string ch2 = string.Empty; //数字位的汉字读法 
            int nzero = 0; //用来计算连续的零值是几个 

            num = Math.Round(Math.Abs(num), 2); //将num取绝对值并四舍五入取2位小数 
            string str4 = ((long)(num * 100)).ToString();
            int j = str4.Length;
            if (j > 15)
            {
                return "溢出";
            }
            str2 = str2.Substring(15 - j); //取出对应位数的str2的值。如：200.55,j为5所以str2=佰拾元角分 

            //循环取出每一位需要转换的值 
            for (i = 0; i < j; i++)
            {
                string str3 = str4.Substring(i, 1); //从原num值中取出的值 
                int temp = Convert.ToInt32(str3); //从原num值中取出的值 
                string ch1; //数字的汉语读法 
                if (i != (j - 3) && i != (j - 7) && i != (j - 11) && i != (j - 15))
                {
                    //当所取位数不为元、万、亿、万亿上的数字时 
                    if (str3 == "0")
                    {
                        ch1 = string.Empty;
                        ch2 = string.Empty;
                        nzero = nzero + 1;
                    }
                    else
                    {
                        if (str3 != "0" && nzero != 0)
                        {
                            ch1 = "零" + str1.Substring(temp * 1, 1);
                            ch2 = str2.Substring(i, 1);
                            nzero = 0;
                        }
                        else
                        {
                            ch1 = str1.Substring(temp * 1, 1);
                            ch2 = str2.Substring(i, 1);
                            nzero = 0;
                        }
                    }
                }
                else
                {
                    //该位是万亿，亿，万，元位等关键位 
                    if (str3 != "0" && nzero != 0)
                    {
                        ch1 = "零" + str1.Substring(temp * 1, 1);
                        ch2 = str2.Substring(i, 1);
                        nzero = 0;
                    }
                    else
                    {
                        if (str3 != "0" && nzero == 0)
                        {
                            ch1 = str1.Substring(temp * 1, 1);
                            ch2 = str2.Substring(i, 1);
                            nzero = 0;
                        }
                        else
                        {
                            if (str3 == "0" && nzero >= 3)
                            {
                                ch1 = string.Empty;
                                ch2 = string.Empty;
                                nzero = nzero + 1;
                            }
                            else
                            {
                                if (j >= 11)
                                {
                                    ch1 = string.Empty;
                                    nzero = nzero + 1;
                                }
                                else
                                {
                                    ch1 = string.Empty;
                                    ch2 = str2.Substring(i, 1);
                                    nzero = nzero + 1;
                                }
                            }
                        }
                    }
                }
                if (i == (j - 11) || i == (j - 3))
                {
                    //如果该位是亿位或元位，则必须写上 
                    ch2 = str2.Substring(i, 1);
                }
                str5 = str5 + ch1 + ch2;

                if (i == j - 1 && str3 == "0")
                {
                    //最后一位（分）为0时，加上“整” 
                    str5 = str5 + "整";
                }
            }
            if (num == 0)
            {
                str5 = "零元整";
            }
            return str5;
        }

        #endregion
    }
}